#include "Polynomial.h"

Polynomial::Polynomial(int m,vector<double> arr)
{
  d=m;
  Coef=arr;
}

Polynomial Polynomial:: operator+(Polynomial p)const
{
  Polynomial f;
  if(d>p.d)
    {
      f.d=d;
      f.Coef=Coef;
      for(int i=0;i<=p.d;i++)
	f.Coef[i]=Coef[i]+p.Coef[i];
      }
  else if(d==p.d)
    {
      int k=0;
      for(int i=d;i>=0;i--)
         if((Coef[i]+p.Coef[i])!=0) 
            {k=i;break;}
      vector<double> coef(k+1);
      for(int j=0;j<=k;j++)
	 coef[j]=Coef[j]+p.Coef[j];
      f.d=k;
      f.Coef=coef;
     } 
  else
    {
      f.d=p.d;
      f.Coef=p.Coef;
      for(int i=0;i<=d;i++)
	f.Coef[i]=Coef[i]+p.Coef[i];
    }
  return f;
}

Polynomial Polynomial:: operator-(Polynomial p)const
{
  Polynomial f;
  f.d=d;
  f.Coef=Coef;
  p = (-1)*p;
  return f+p;
}

Polynomial Polynomial:: operator*(const Polynomial &p)const
{
  Polynomial f;
  f.d=d+p.d;
  vector<double> coef(f.d+1,0);
  for(int i=0;i<=d;i++)
    for(int j=0;j<=p.d;j++)
      {
	coef[i+j]=coef[i+j]+Coef[i]*p.Coef[j];
      }
  f.Coef=coef;
  return f;
}

Polynomial operator*(double c,const Polynomial &p)
{
  Polynomial P;
  if(c==0){P.d=0;vector<double> arr={0};P.Coef=arr;return P;}
  P.d=p.d;
  P.Coef=p.Coef;
  for(int i=0;i<=p.d;i++)
    P.Coef[i]=c*P.Coef[i];
  return P;
}

double Polynomial::get_value(double x)const
{
  double _sum=0;
  for(int i=0;i<=d;i++)
    _sum=_sum+Coef[i]*pow(x,i);
  return _sum;
}

Polynomial Polynomial:: get_deri()const
{
  Polynomial f;
  if(d==0){f.d=0;vector<double> arr={0};f.Coef=arr;return f;}
  f.d=d-1;
  vector<double> coef(f.d+1,0);
  for(int i=0;i<=f.d;i++)
    coef[i]=Coef[i+1]*(i+1);
  f.Coef=coef;
  return f;  
}

double Polynomial::get_deri_value(double x)const
{
  Polynomial f=this->get_deri();
  return f.get_value(x);
}

int Polynomial:: get_d()const{return d;}

vector<double> Polynomial:: get_Coef()const{return Coef;}

ostream& operator<<(ostream& os,const Polynomial &p)
{
  for(int i=p.d;i>=1;i--)
      if(p.Coef[i]!=0)
	{
	  if(abs(p.Coef[i])!=1)
	    {
	      if(i==1){
	      if(i==p.d)
		os<<p.Coef[i]<<"x";
	      else
		{
		  if(p.Coef[i]>0)
		    os<<"+"<<p.Coef[i]<<"x";
		  else
		    os<<"-"<<abs(p.Coef[i])<<"x";
		}
	      }
	      else
		{
		  if(i==p.d)
		    os<<p.Coef[i]<<"x^"<<i;
		  else
		    {
		      if(p.Coef[i]>0)
			os<<"+"<<p.Coef[i]<<"x^"<<i;
		      else
			os<<"-"<<abs(p.Coef[i])<<"x^"<<i;
		    }
		}
	    }
	  else
	    {
	      if(i==1){
	      if(i==p.d)
		if(p.Coef[i]==1)
		  os<<"x";
		else
		  os<<"-"<<"x";
	      else
		if(p.Coef[i]==1)
		  os<<"+"<<"x";
		else
		  os<<"-"<<"x";
	      }
	      else
		{
		  if(i==p.d)
		    if(p.Coef[i]==1)
		      os<<"x^"<<i;
		    else
		      os<<"-"<<"x^"<<i;
		  else
		    if(p.Coef[i]==1)
		      os<<"+"<<"x^"<<i;
		    else
		      os<<"-"<<"x^"<<i;
		}
	    }
	}
  if(p.d!=0)
    if(p.Coef[0]!=0)
      {
	if(p.Coef[0]>0) os<<"+"<<p.Coef[0];
	else os<<"-"<<abs(p.Coef[0]);
      }
  if(p.d==0)
    os<<p.Coef[0];
  return os;
}
